﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.LIB;
using YArchitech.Revit;
using YJKRGeometry;

namespace HYOpeningDetail
{
	internal class BoundaryBasedRectComponent : RectangleComponent
	{
		public void DimBoxFunction(ElementInfo dicElementInfo, Wall wall, List<XYZ> lstBoxVertexes, ViewPlan viewPlan, Dictionary<XYZ, DataWall> dicWallCurve, Dictionary<XYZ, List<Curve>> dicCombineGridCurve, Autodesk.Revit.DB.Document doc, int iBoxCategory)
		{
			this.m_doc = doc;
			this.GetIntersectDepth(wall, dicElementInfo, lstBoxVertexes);
			Transaction transaction = new Transaction(this.m_doc, "Dim");
			try
			{
				transaction.Start();
				if (OpeningViewDataSetForm.BRadSelGrid)
				{
					this.CreateLocationDimensionByGridCurve(dicElementInfo, lstBoxVertexes, viewPlan, dicCombineGridCurve);
				}
				else
				{
					this.CreateLocationDimensionByWallCurve(dicElementInfo, wall, lstBoxVertexes, viewPlan, dicWallCurve);
				}
				this.CreateLeaderDimension(dicElementInfo, lstBoxVertexes, viewPlan, iBoxCategory);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		private void CreateLeaderDimension(ElementInfo dicElementInfo, List<XYZ> lstBoxVertexes, ViewPlan viewPlan, int iBoxCategory)
		{
			string strLevelText = null;
			string strFamText = null;
			double elevation = viewPlan.GenLevel.Elevation;
			this.GetDimText(dicElementInfo, iBoxCategory, elevation, ref strLevelText, ref strFamText);
			lstBoxVertexes = (from pt in lstBoxVertexes
			orderby pt.Y
			select pt).ToList<XYZ>();
			XYZ xyz = lstBoxVertexes[0].Add(lstBoxVertexes[1]).Divide(2.0);
			XYZ ptDimPosionFir = new XYZ(xyz.X + NumbericTools.mmToFeet(800.0), xyz.Y - NumbericTools.mmToFeet(400.0), xyz.Z);
			base.LeaderDimension(xyz, ptDimPosionFir, strFamText, strLevelText, viewPlan);
		}

		private bool CreateLocationDimensionByWallCurve(ElementInfo dicElementInfo, Wall wall, List<XYZ> lstBoxVertexes, ViewPlan viewPlan, Dictionary<XYZ, DataWall> dicWallCurve)
		{
			Curve curve = (wall.Location as LocationCurve).Curve;
			XYZ ptFamInstance = null;
			LocationPoint locationPoint = dicElementInfo.element.Location as LocationPoint;
			if (dicElementInfo.revitLink != null)
			{
				Transform transform = dicElementInfo.revitLink.GetTransform();
				ptFamInstance = transform.OfPoint(locationPoint.Point);
			}
			else
			{
				ptFamInstance = locationPoint.Point;
			}
			Dictionary<XYZ, DataWall> dictionary;
			if (this.IsBoxOnWall(wall, dicWallCurve, out dictionary))
			{
				dicWallCurve = dictionary;
			}
			dicWallCurve = (from k in dicWallCurve
			orderby k.Key.DistanceTo(ptFamInstance)
			select k).ToDictionary((KeyValuePair<XYZ, DataWall> k) => k.Key, (KeyValuePair<XYZ, DataWall> k) => k.Value);
			if (dicWallCurve.Count <= 0)
			{
				return false;
			}
			DataWall value = dicWallCurve.ElementAt(0).Value;
			XYZ key = dicWallCurve.ElementAt(0).Key;
			Line line = curve as Line;
			YJKLine hyline = new YJKLine(line);
			Line line2 = value.curvrFirst as Line;
			Line line3 = value.curveSecond as Line;
			double dFirstWallWidth = value.dFirstWallWidth;
			double dSecondWallWidth = value.dSecondWallWidth;
			if (!hyline.IsParallel(line2) && !hyline.IsParallel(line3))
			{
				return false;
			}
			Line dimLine = null;
			double dOffset = 0.0;
			if (hyline.IsParallel(line2))
			{
				dimLine = line3;
				dOffset = dFirstWallWidth;
			}
			else if (hyline.IsParallel(line3))
			{
				dimLine = line2;
				dOffset = dSecondWallWidth;
			}
			XYZ xyz = new XYZ(ptFamInstance.X, ptFamInstance.Y, line.GetEndPoint(0).Z);
			XYZ project = new YJKLine(dimLine).GetProject(xyz);
			XYZ vector = xyz.Subtract(project).Normalize();
			List<XYZ> lstNewBoxVertexes = new List<XYZ>();
			lstBoxVertexes.ForEach(delegate(XYZ pt)
			{
				lstNewBoxVertexes.Add(new XYZ(pt.X, pt.Y, dimLine.GetEndPoint(0).Z));
			});
			Curve dimLine2 = dimLine;
			Curve newDimCurve = PublicFunction.CreateOffsetCurve(dimLine2, vector, dOffset);
			lstNewBoxVertexes = (from a in lstNewBoxVertexes
			orderby newDimCurve.Distance(a)
			select a).ToList<XYZ>();
			XYZ project2 = new YJKLine(newDimCurve as Line).GetProject(lstNewBoxVertexes[0]);
			XYZ vectorMove = lstNewBoxVertexes[0].Subtract(lstNewBoxVertexes[1]).Normalize();
			Line dimNewLine = Line.CreateBound(project2, lstNewBoxVertexes[0]);
			base.CreateDetailLine(lstNewBoxVertexes[0], project2, vectorMove, viewPlan, dimNewLine, false);
			return true;
		}

		private bool CreateLocationDimensionByGridCurve(ElementInfo dicElementInfo, List<XYZ> lstBoxVertexes, ViewPlan viewPlan, Dictionary<XYZ, List<Curve>> dicCombineGridCurve)
		{
			XYZ ptFamInstance = null;
			LocationPoint locationPoint = dicElementInfo.element.Location as LocationPoint;
			if (dicElementInfo.revitLink != null)
			{
				Transform transform = dicElementInfo.revitLink.GetTransform();
				ptFamInstance = transform.OfPoint(locationPoint.Point);
			}
			else
			{
				ptFamInstance = locationPoint.Point;
			}
			XYZ ptGridIntersect = null;
			List<Curve> list = null;
			dicCombineGridCurve = (from k in dicCombineGridCurve
			orderby k.Key.DistanceTo(ptFamInstance)
			select k).ToDictionary((KeyValuePair<XYZ, List<Curve>> k) => k.Key, (KeyValuePair<XYZ, List<Curve>> k) => k.Value);
			if (dicCombineGridCurve.Count > 0)
			{
				ptGridIntersect = dicCombineGridCurve.ElementAt(0).Key;
				list = dicCombineGridCurve.ElementAt(0).Value;
				List<XYZ> lstNewBoxVertexes = new List<XYZ>();
				lstBoxVertexes.ForEach(delegate(XYZ i)
				{
					lstNewBoxVertexes.Add(i);
				});
				lstBoxVertexes.Add(lstBoxVertexes[0]);
				List<Line> list2 = new List<Line>();
				List<XYZ> list3 = new List<XYZ>();
				for (int j = 0; j < lstBoxVertexes.Count - 1; j++)
				{
					XYZ xyz = new XYZ(lstBoxVertexes[j].X, lstBoxVertexes[j].Y, ptGridIntersect.Z);
					XYZ xyz2 = new XYZ(lstBoxVertexes[j + 1].X, lstBoxVertexes[j + 1].Y, ptGridIntersect.Z);
					Line item = Line.CreateBound(xyz, xyz2);
					list2.Add(item);
					if (j < lstBoxVertexes.Count)
					{
						list3.Add(xyz);
					}
				}
				new XYZ(ptFamInstance.X, ptFamInstance.Y, ptGridIntersect.Z);
				List<XYZ> list4 = new List<XYZ>();
				List<Line> list5 = new List<Line>();
				foreach (Line line in list2)
				{
					foreach (Curve curve in list)
					{
						XYZ xyz3 = new YJKLine(curve as Line).IntersectionPoint(line);
						if (xyz3 != null)
						{
							list4.Add(xyz3);
							list5.Add(line);
						}
					}
				}
				if (list4.Count == 0)
				{
					list3 = (from pt in list3
					orderby pt.DistanceTo(ptGridIntersect)
					select pt).ToList<XYZ>();
					XYZ xyz4 = list3[0];
					List<XYZ> list6 = new List<XYZ>();
					foreach (Curve curve2 in list)
					{
						YJKLine hyline = new YJKLine(curve2 as Line);
						list6.Add(hyline.GetProject(xyz4));
					}
					xyz4.Subtract(list6[0]).Normalize();
					XYZ ptVector = xyz4.Subtract(list6[1]).Normalize();
					base.CteateDim(list6[0], xyz4, ptVector, viewPlan);
					base.CteateDim(list6[1], xyz4, ptVector, viewPlan);
				}
				if (list4.Count == 2)
				{
					Curve grdCurve = null;
					foreach (Curve curve3 in list)
					{
						YJKLine hyline2 = new YJKLine(curve3 as Line);
						foreach (Line otherLine in list5)
						{
							if (hyline2.IsParallel(otherLine))
							{
								grdCurve = curve3;
								break;
							}
						}
					}
					list4 = (from a in list4
					orderby grdCurve.Distance(a)
					select a).ToList<XYZ>();
					list5 = (from b in list5
					orderby b.Distance(ptGridIntersect)
					select b).ToList<Line>();
					YJKLine hyline3 = new YJKLine(grdCurve as Line);
					XYZ project = hyline3.GetProject(list5[0].GetEndPoint(0));
					hyline3.GetProject(list5[0].GetEndPoint(1));
					XYZ ptVector2 = list5[0].GetEndPoint(0).Subtract(list4[0]).Normalize();
					XYZ xyz5 = list4[0].Subtract(ptGridIntersect).Normalize();
					base.CteateDim(list5[0].GetEndPoint(0), project, ptVector2, viewPlan);
					base.CteateDim(list5[0].GetEndPoint(0), list4[0], -xyz5, viewPlan);
					base.CteateDim(list5[0].GetEndPoint(1), list4[0], -xyz5, viewPlan);
				}
				if (list4.Count == 4)
				{
					List<Line> list7 = new List<Line>();
					lstNewBoxVertexes = (from pt in lstNewBoxVertexes
					orderby pt.DistanceTo(ptGridIntersect)
					select pt).ToList<XYZ>();
					foreach (Line line2 in list2)
					{
						if (new YJKLine(line2).IsPointOnLine(lstNewBoxVertexes[0]))
						{
							list7.Add(line2);
						}
					}
					using (List<Line>.Enumerator enumerator = list7.GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							Line boxIntersectLine = enumerator.Current;
							list4 = (from pt in list4
							orderby boxIntersectLine.Distance(pt)
							select pt).ToList<XYZ>();
							XYZ xyz6 = ptGridIntersect.Subtract(list4[0]).Normalize();
							base.CteateDim(boxIntersectLine.GetEndPoint(0), list4[0], -xyz6, viewPlan);
							base.CteateDim(boxIntersectLine.GetEndPoint(0), boxIntersectLine.GetEndPoint(1), -xyz6, viewPlan);
						}
					}
				}
				return true;
			}
			return false;
		}

		private bool GetDimText(ElementInfo dicElementInfo, int iBoxCategory, double dLevelValue, ref string strLevelText, ref string strFamText)
		{
			List<XYZ> list = this.GetElementBottomXYZ(dicElementInfo);
			if (list == null || list.Count < 0)
			{
				return false;
			}
			list = (from pt in list
			orderby pt.Z
			select pt).ToList<XYZ>();
			XYZ xyz = list[0];
			FamilyInstance familyInstance = dicElementInfo.element as FamilyInstance;
			double num = 0.0;
			double num2 = 0.0;
			double value = 0.0;
			double value2 = 0.0;
			double value3 = 0.0;
			double value4 = 0.0;
			double value5 = 0.0;
			double value6 = 0.0;
			Parameter parameter = base.GetParameter(familyInstance, "长度");
			Parameter parameter2 = base.GetParameter(familyInstance, "宽度");
			Parameter parameter3 = base.GetParameter(familyInstance, "高度");
			Parameter parameter4 = base.GetParameter(familyInstance, "进深");
			Parameter parameter5 = base.GetParameter(familyInstance, "厚度");
			Parameter parameter6 = base.GetParameter(familyInstance, "风口宽度");
			Parameter parameter7 = base.GetParameter(familyInstance, "风口高度");
			Parameter parameter8 = base.GetParameter(familyInstance, "洞口宽度");
			Parameter parameter9 = base.GetParameter(familyInstance, "洞口高度");
			Parameter parameter10 = base.GetParameter(familyInstance, "洞口深度");
			Parameter parameter11 = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
			Parameter parameter12 = familyInstance.get_Parameter(BuiltInParameter.SCHEDULE_LEVEL_PARAM);
			if (parameter != null)
			{
				value6 = NumbericTools.feetTomm(parameter.AsDouble());
			}
			if (parameter2 != null)
			{
				num = NumbericTools.feetTomm(parameter2.AsDouble());
			}
			if (parameter3 != null)
			{
				num2 = NumbericTools.feetTomm(parameter3.AsDouble());
			}
			if (parameter4 != null)
			{
				value6 = NumbericTools.feetTomm(parameter4.AsDouble());
			}
			if (parameter5 != null)
			{
				value6 = NumbericTools.feetTomm(parameter5.AsDouble());
			}
			if (parameter6 != null)
			{
				value = NumbericTools.feetTomm(parameter6.AsDouble());
			}
			if (parameter7 != null)
			{
				value2 = NumbericTools.feetTomm(parameter7.AsDouble());
			}
			if (parameter8 != null)
			{
				value3 = NumbericTools.feetTomm(parameter8.AsDouble());
			}
			if (parameter9 != null)
			{
				value4 = NumbericTools.feetTomm(parameter9.AsDouble());
			}
			if (parameter10 != null)
			{
				value5 = NumbericTools.feetTomm(parameter10.AsDouble());
			}
			if (parameter11 != null)
			{
				NumbericTools.feetTomm(parameter11.AsDouble());
			}
			if (parameter12 != null)
			{
				parameter12.AsDouble();
			}
			double num3 = NumbericTools.feetTomm(xyz.Z - dLevelValue);
			string text = Convert.ToInt32(num).ToString();
			string text2 = Convert.ToInt32(num2).ToString();
			string text3 = familyInstance.Symbol.Family.Name.ToString();
			string text4 = Convert.ToInt32(value).ToString();
			string text5 = Convert.ToUInt32(value2).ToString();
			string text6 = Convert.ToInt32(value3).ToString();
			string text7 = Convert.ToInt32(value4).ToString();
			string text8 = Convert.ToInt32(value5).ToString();
			string text9 = Convert.ToUInt32(value6).ToString();
			if (iBoxCategory == 0)
			{
				if (Geometry.IsEqual(this.m_dBoxDepth, 0.0))
				{
					strFamText = string.Concat(new string[]
					{
						"消火栓",
						text9,
						"X",
						text2,
						"(H)X",
						text
					});
				}
				else
				{
					string text10 = Convert.ToInt32(NumbericTools.feetTomm(this.m_dBoxDepth)).ToString();
					strFamText = string.Concat(new string[]
					{
						"消火栓",
						text9,
						"X",
						text2,
						"(H)X",
						text10
					});
				}
				strLevelText = "洞底标高: H+" + Convert.ToInt32(num3).ToString();
			}
			else if (iBoxCategory == 1 || iBoxCategory == 2 || iBoxCategory == 3)
			{
				if (text3.Equals("前端箱"))
				{
					double num4 = 0.0;
					double value7 = 0.0;
					double num5 = 0.0;
					if (parameter != null)
					{
						num4 = NumbericTools.feetTomm(parameter.AsDouble());
					}
					if (parameter4 != null)
					{
						value7 = NumbericTools.feetTomm(parameter4.AsDouble());
					}
					if (parameter2 != null)
					{
						num5 = NumbericTools.feetTomm(parameter2.AsDouble());
					}
					strFamText = string.Concat(new string[]
					{
						text3,
						Convert.ToInt32(num4 + 100.0).ToString(),
						"X",
						Convert.ToInt32(num5 + 100.0).ToString(),
						"(H)X",
						Convert.ToInt32(value7).ToString()
					});
				}
				else
				{
					strFamText = string.Concat(new string[]
					{
						text3,
						Convert.ToInt32(num + 100.0).ToString(),
						"X",
						Convert.ToInt32(num2 + 100.0).ToString(),
						"(H)X",
						text9
					});
				}
				string text11 = Convert.ToInt32(num3 - 50.0).ToString();
				if (text11.Contains("-"))
				{
					strLevelText = "洞底标高: H" + text11;
				}
				else
				{
					strLevelText = "洞底标高: H+" + text11;
				}
			}
			else if (iBoxCategory == 4)
			{
				strFamText = "分集水器";
				strLevelText = string.Concat(new string[]
				{
					text6,
					"X",
					text7,
					"(H)X",
					text8
				});
			}
			else
			{
				strFamText = string.Concat(new string[]
				{
					"风口",
					text4,
					"X",
					text5,
					"(H)"
				});
				strLevelText = "洞底标高: H+" + Convert.ToInt32(num3).ToString();
			}
			return true;
		}

		private List<XYZ> GetElementBottomXYZ(ElementInfo dicElementInfo)
		{
			LocationPoint locationPoint = dicElementInfo.element.Location as LocationPoint;
			if (dicElementInfo.revitLink != null)
			{
				dicElementInfo.revitLink.GetTransform().OfPoint(locationPoint.Point);
			}
			else
			{
				XYZ point = locationPoint.Point;
			}
			List<Face> list = new List<Face>();
			List<XYZ> list2 = new List<XYZ>();
			PublicFunction.GetAllFace(dicElementInfo.element, ref list, XYZ.BasisZ, null);
			foreach (Face face in list)
			{
				PlanarFace planarFace = face as PlanarFace;
				if (planarFace != null)
				{
					Transform totalTransform = (dicElementInfo.element as FamilyInstance).GetTotalTransform();
					if (totalTransform != null)
					{
						XYZ item = totalTransform.OfPoint(planarFace.Origin);
						list2.Add(item);
					}
				}
			}
			return list2;
		}

		private void GetIntersectDepth(Wall intersectWall, ElementInfo elementInfo, List<XYZ> lstBoxVertexes)
		{
			FamilyInstance familyInstance = elementInfo.element as FamilyInstance;
			XYZ ptSec = familyInstance.FacingOrientation.Normalize();
			familyInstance.HandOrientation.Normalize();
			XYZ xyz = intersectWall.Orientation.Normalize();
			Curve wallCurve = (intersectWall.Location as LocationCurve).Curve;
			double wallWidth = PublicFunction.GetWallWidth(intersectWall);
			List<Curve> list = new List<Curve>();
			list.Add(PublicFunction.CreateOffsetCurve(wallCurve, xyz, wallWidth));
			list.Add(PublicFunction.CreateOffsetCurve(wallCurve, -xyz, wallWidth));
			List<XYZ> lstNewBoxVertexes = new List<XYZ>();
			lstBoxVertexes.ForEach(delegate(XYZ pt)
			{
				lstNewBoxVertexes.Add(new XYZ(pt.X, pt.Y, wallCurve.GetEndPoint(0).Z));
			});
			List<Curve> list2 = new List<Curve>();
			list2.Add(Line.CreateBound(lstNewBoxVertexes[0], lstNewBoxVertexes[1]));
			list2.Add(Line.CreateBound(lstNewBoxVertexes[1], lstNewBoxVertexes[2]));
			list2.Add(Line.CreateBound(lstNewBoxVertexes[2], lstNewBoxVertexes[3]));
			list2.Add(Line.CreateBound(lstNewBoxVertexes[3], lstNewBoxVertexes[0]));
			XYZ xyz2 = null;
			Curve verticalCurve = this.GetVerticalCurve(list2, list, ref xyz2);
			if (verticalCurve != null)
			{
				Line line = verticalCurve as Line;
				if (!this.IsSameDirection(line.Direction, ptSec))
				{
					this.m_dBoxDepth = line.GetEndPoint(0).DistanceTo(xyz2);
					return;
				}
				this.m_dBoxDepth = line.GetEndPoint(1).DistanceTo(xyz2);
			}
		}

		private Curve GetVerticalCurve(List<Curve> lstCurBox, List<Curve> lstWallCurve, ref XYZ ptIntersect)
		{
			Curve result = null;
			foreach (Curve curve in lstCurBox)
			{
				YJKCurve hycurve = new YJKCurve(curve);
				foreach (Curve otherCurve in lstWallCurve)
				{
					ptIntersect = hycurve.IntersectionPoint(otherCurve);
					if (ptIntersect != null)
					{
						result = curve;
						return result;
					}
				}
			}
			return result;
		}

		private bool IsBoxOnWall(Wall intersectWall, Dictionary<XYZ, DataWall> dicWallCurve, out Dictionary<XYZ, DataWall> tempValue)
		{
			Curve mepcurveLine = PublicFunction.GetMEPCurveLine(intersectWall);
			tempValue = new Dictionary<XYZ, DataWall>();
			foreach (KeyValuePair<XYZ, DataWall> keyValuePair in dicWallCurve)
			{
				if (this.IsSameCurve(mepcurveLine, keyValuePair.Value.curvrFirst) || this.IsSameCurve(mepcurveLine, keyValuePair.Value.curveSecond))
				{
					tempValue.Add(keyValuePair.Key, keyValuePair.Value);
				}
			}
			return tempValue.Count != 0;
		}

		private bool IsSameCurve(Curve curveFir, Curve curveSec)
		{
			Line line = curveFir as Line;
			Line line2 = curveSec as Line;
			if (Geometry.IsEqual(line.Direction.Normalize().AngleTo(line2.Direction.Normalize()), 0.0))
			{
				if (line.GetEndPoint(0).IsAlmostEqualTo(line2.GetEndPoint(0)) && line.GetEndPoint(1).IsAlmostEqualTo(line2.GetEndPoint(1)))
				{
					return true;
				}
			}
			else if (line.GetEndPoint(0).IsAlmostEqualTo(line2.GetEndPoint(1)) && line.GetEndPoint(1).IsAlmostEqualTo(line2.GetEndPoint(0)))
			{
				return true;
			}
			return false;
		}

		private bool IsSameDirection(XYZ ptFir, XYZ ptSec)
		{
			return Geometry.IsEqual(ptFir.Normalize().AngleTo(ptSec.Normalize()), 0.0);
		}

		private double m_dBoxDepth;
	}
}
